#include "message.h"

/* ------------------------------------------------------------------------- */
/* Estrutura da mensagem e respectivos metodos */
message::message(byte *msg)
{
    if( msg )
        this->copyMessage(msg, this->messageString);
}

byte message::getStamp()
{
    return this->messageString[0];
}
size_t message::getSize()
{
    return size_t(this->messageString[1] >> 3);
}
size_t message::getSeq()
{
    return size_t(this->messageString[1]&7); /* 7 = 111 */
}
byte message::getType()
{
    return this->messageString[2];
}
const byte *message::getData()
{
    return &this->messageString[3];
}
byte message::getParit()
{
    return this->messageString[this->getSize()+1];
}
const byte *message::getMessage()
{
    return this->messageString;
}
bool message::setMessage(byte seq, byte type, const byte *data, size_t dataSize)
{
    if(seq > 7 || dataSize > MAX_DATA_SIZE /* ! data */ )
        return false;

    /* Sets stamp */
    this->messageString[0] = byte(STAMP);

    /* Sets Size and Seq */
    this->messageString[1] = byte((dataSize+2) << 3) + seq;

    /* Sets type */
    this->messageString[2] = type;

    /* Sets data */
    for(size_t i=0 ; i<dataSize ; i++)
        this->messageString[i+3] = data[i];

    /* Gera paridade */
    this->generateParit();

    return true;
}
bool message::copyMessage(const byte *from,  byte *to)
{
    if( ! from || ! to )
        return false;

    for(size_t i=0 ; i< this->messageSize(from)+2; i++)
        to[i] = from[i];

    return true;
}

/* ------------------------------------------------------------------------ */
/* Manipulação das mensagens. */

byte message::messageStamp(const byte *msg)
{
    return msg[0];
}
size_t message::messageSize(const byte *msg)
{
    return size_t(msg[1] >> 3);
}
size_t message::messageSeq(const byte *msg)
{
    return size_t(msg[1]&7); /* 7 = 111 */
}
byte message::messageType(const byte *msg)
{
    return msg[2];
}
const byte *message::messageData(const byte *msg)
{
    return &msg[3];
}
byte message::messageParit(const byte *msg)
{
    return msg[this->messageSize(msg)+2];
}

/* Verifica se a mensagem contida no msg é valida */
bool message::validateMessage()
{
    if( this->getStamp() != STAMP )
        return false;

    /* Verifica paridade */
    byte paritCheck = 0;

    for( size_t i=1 ; i < this->getSize()+2 ; i++ )
        paritCheck ^= this->messageString[i];

    return paritCheck ? false : true;
}

void message::generateParit()
{
    byte parit = 0;

    /* Faz o xor bit a bit. */
    for( size_t i=1 ; i < this->getSize()+1 ; i++ )
        parit ^= this->messageString[i];

    this->messageString[this->getSize()+1] = parit;
}
